package com.tengju.settlement.infrastructure.repository;

import com.tengju.settlement.domain.model.account.UserIdCode;
import com.tengju.settlement.domain.model.depository.*;
import com.tengju.settlement.domain.shared.IdObject;
import com.tengju.settlement.infrastructure.persistence.mybatis.dataobject.DepositoryAccountDO;
import com.tengju.settlement.infrastructure.persistence.mybatis.mapper.tengju.custom.DepositoryAccountMapper;
import com.tengju.settlement.infrastructure.repository.convert.DepositoryAccountConvert;
import com.tengju.settlement.infrastructure.shared.InfraException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class DepositoryAccountRepositoryImpl implements DepositoryAccountRepository {

    @Resource
    DepositoryAccountMapper depositoryAccountMapper;


    @Override
    public List<DepositoryAccount> getByLicenseStatus(License license, List<AccountStatus> status, DepositoryChannel depositoryChannel) {
        List<Integer> statusList = status.stream().map(AccountStatus::getVal).collect(Collectors.toList());
        List<DepositoryAccountDO> depositoryAccountDOList =
                depositoryAccountMapper.getByLicenseStatus(license.getLicenseType().getInnerVal(),
                        license.getLicenseNumber(),
                        statusList,
                        depositoryChannel.getInnerVal());
        return depositoryAccountDOList.stream()
                .map(DepositoryAccountConvert::convertToModel).collect(Collectors.toList());
    }


    @Override
    public DepositoryAccount getByIdCodeLicenseStatus(UserIdCode idCode, License license, AccountStatus status, DepositoryChannel depositoryChannel) {
        DepositoryAccountDO depositoryAccountDO =
                depositoryAccountMapper.getByIdCodeLicenseStatus(idCode.getValue(),
                        license.getLicenseType().getInnerVal(),
                        license.getLicenseNumber(),
                        status.getVal(),
                        depositoryChannel.getInnerVal());
        return DepositoryAccountConvert.convertToModel(depositoryAccountDO);
    }

    @Override
    public List<DepositoryAccount> getByIdCodeStatus(UserIdCode idCode, List<AccountStatus> status, DepositoryChannel depositoryChannel) {
        List<Integer> statusVal = status.stream().map(AccountStatus::getVal).collect(Collectors.toList());
        List<DepositoryAccountDO> depositoryAccountDOList =
                depositoryAccountMapper.getByIdCodeStatus(idCode.getValue(),
                        statusVal, depositoryChannel.getInnerVal());
        return depositoryAccountDOList.stream().map(DepositoryAccountConvert::convertToModel).collect(Collectors.toList());
    }

    @Override
    public DepositoryAccount getByIdCodeLicense(UserIdCode idCode, License license, DepositoryChannel depositoryChannel) {
        DepositoryAccountDO depositoryAccountDO =
                depositoryAccountMapper.getByIdCodeLicense(idCode.getValue(),
                        license.getLicenseType().getInnerVal(), license.getLicenseNumber(),
                        depositoryChannel.getInnerVal());
        return DepositoryAccountConvert.convertToModel(depositoryAccountDO);
    }

    @Override
    public Integer countByIdCodeStatus(UserIdCode idCode, List<AccountStatus> status, DepositoryChannel depositoryChannel) {
        List<Integer> statusVal = status.stream()
                .map(AccountStatus::getVal).collect(Collectors.toList());
        return depositoryAccountMapper.countByIdCodeStatus(idCode.getValue(), statusVal, depositoryChannel.getInnerVal());
    }

    @Override
    public DepositoryAccount getByDepAccountId(DepositoryAccountId depositoryAccountId) {
        DepositoryAccountDO depositoryAccountDO =
                depositoryAccountMapper.getByDepAccountId(depositoryAccountId.getValue());
        return DepositoryAccountConvert.convertToModel(depositoryAccountDO);
    }

    @Override
    public List<DepositoryAccount> getByIdCodesStatusNormal(List<UserIdCode> idCode, DepositoryChannel depositoryChannel) {
        List<Long> idCodeVal = idCode.stream().map(IdObject::getValue).collect(Collectors.toList());
        List<DepositoryAccountDO> depositoryAccountDOList = depositoryAccountMapper
                .getByIdCodesStatus(idCodeVal, List.of(AccountStatus.NORMAL.getVal()), depositoryChannel.getInnerVal());
        return depositoryAccountDOList.stream()
                .map(DepositoryAccountConvert::convertToModel).collect(Collectors.toList());
    }

    @Override
    public DepositoryAccount getByIdCodeStatusNormal(UserIdCode idCode, DepositoryChannel depositoryChannel) {
        List<DepositoryAccountDO> depositoryAccountDOList =
                depositoryAccountMapper.getByIdCodeStatus(idCode.getValue(), List.of(AccountStatus.NORMAL.getVal()), depositoryChannel.getInnerVal());
        if (CollectionUtils.isEmpty(depositoryAccountDOList)) {
            return null;
        }
        return DepositoryAccountConvert.convertToModel(depositoryAccountDOList.get(0));
    }

    @Override
    public DepositoryAccount getByIdCodeStatusAuthing(UserIdCode idCode, DepositoryChannel depositoryChannel) {
        List<DepositoryAccountDO> depositoryAccountDOList =
                depositoryAccountMapper.getByIdCodeStatus(idCode.getValue(), List.of(AccountStatus.CARD_BINDING.getVal()),
                        depositoryChannel.getInnerVal());
        if (CollectionUtils.isEmpty(depositoryAccountDOList)) {
            return null;
        }
        return DepositoryAccountConvert.convertToModel(depositoryAccountDOList.get(0));
    }

    @Override
    public void updateStatus(DepositoryAccount account) {
        DepositoryAccountDO depositoryAccountDO = DepositoryAccountConvert.convertToDO(account);
        int count = depositoryAccountMapper.updateStatus(depositoryAccountDO);
        if (count != 1) {
            log.error("账户状态更新失败: request:{}", account);
            throw new InfraException("账户状态更新失败: 用户idCode: " + account.getIdCode().getValue());
        }
    }

    @Override
    public DepositoryAccount save(DepositoryAccount account) {
        DepositoryAccountDO depositoryAccountDO = DepositoryAccountConvert.convertToDO(account);
        depositoryAccountMapper.insert(depositoryAccountDO);

        return DepositoryAccountConvert.convertToModel(depositoryAccountDO);

    }

}
